﻿#region Licence
// Copyright (c) 2008 James Gregory (james@jagregory.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of James Gregory nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;
using Rhino.Commons;

namespace JAGregory.BooPlugin.Language
{
    class BooLanguage : LanguageService
    {
        private LanguagePreferences preferences;
        private BooScanner scanner;
        private readonly BooInlineParser inlineParser = new BooInlineParser();
        private static readonly BooColorableItem[] colorableItems = {
            new BooColorableItem("Keyword", COLORINDEX.CI_BLUE, COLORINDEX.CI_USERTEXT_BK),
            new BooColorableItem("Comment", COLORINDEX.CI_DARKGREEN, COLORINDEX.CI_USERTEXT_BK),
            new BooColorableItem("Identifier", COLORINDEX.CI_SYSPLAINTEXT_FG, COLORINDEX.CI_USERTEXT_BK),
            new BooColorableItem("String", COLORINDEX.CI_MAROON, COLORINDEX.CI_USERTEXT_BK),
            new BooColorableItem("Number", COLORINDEX.CI_SYSPLAINTEXT_FG, COLORINDEX.CI_USERTEXT_BK),
            new BooColorableItem("Text", COLORINDEX.CI_SYSPLAINTEXT_FG, COLORINDEX.CI_USERTEXT_BK)
        };

        public override LanguagePreferences GetLanguagePreferences()
        {
            if (preferences == null)
            {
                preferences = new LanguagePreferences(Site, typeof(BooLanguage).GUID, Name);
                preferences.Init();
            }

            return preferences;
        }

        public override IScanner GetScanner(IVsTextLines buffer)
        {
            if (scanner == null)
                scanner = new BooScanner();

            return scanner;
        }

        public override Source CreateSource(IVsTextLines buffer)
        {
            return new BooSource(this, buffer, new Colorizer(this, buffer, GetScanner(buffer)));
        }

        public override AuthoringScope ParseSource(ParseRequest req)
        {
            Guard.Against<ArgumentNullException>(req == null, "Request cannot be null.");

            if (IsMemberSelect(req))
                return inlineParser.GetMemberSelectScope(req, GetSource(req.View));

            return new BooScope(); // just give it an empty scope to stop it complaining
        }

        private bool IsMemberSelect(ParseRequest req)
        {
            return req.Reason == ParseReason.MemberSelect || req.Reason == ParseReason.MemberSelectAndHighlightBraces;
        }

        public override string GetFormatFilterList()
        {
            return @"Boo File (*.boo)
*.boo";
        }

        public override string Name
        {
            get { return "Boo"; }
        }

        public override int GetItemCount(out int count)
        {
            count = colorableItems.Length;
            
            return VSConstants.S_OK;
        }

        public override int GetColorableItem(int index, out IVsColorableItem item)
        {
            Guard.Against<ArgumentOutOfRangeException>(index < 1, "index");

            item = colorableItems[index - 1];
            return VSConstants.S_OK;
        }
    }
}